﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SerialPortHelper.StrategyPattern
{
    public class SimpleDecodedDataFrame : DecodedData
    {
        //帧头标志
        private bool isHeadRecive = false;

        //帧长度
        private int frameLength = 0;

        //帧是否是有效数据
        private bool frameCheckOk = false;


        /// <summary>
        /// 实现算法解析数据,并返回帧或空
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override byte[] decodeDataFrame(Queue<byte> bufferQueue)
        {
            //解析获取帧头
            //如果没有帧头(判断队列中,是否从枕头开始,假设队列:{0x01,0x02,0x7F},我们就需要将0x7F移到最前面来,0x01,0x02是需要丢弃的)
            if (isHeadRecive == false)
            {
                foreach (byte item in bufferQueue.ToArray())
                {
                    if (item != 0x7F)
                    {
                        //将当前字节出列
                        bufferQueue.Dequeue();
                        Console.WriteLine("not 0x7F,Dequeue!!");
                    }
                    else
                    {
                        // get 0X7F from bufferQueue
                        isHeadRecive = true;
                        Console.WriteLine("0x7F is recived!!");
                        break;
                    }
                }
            }

            //如果是帧头
            if (isHeadRecive == true)
            {
                //判断有数据帧长度(有帧头0x7F(1字节)和长度(1字节))
                if (bufferQueue.Count >= 2)
                {
                    Console.WriteLine(DateTime.Now.ToLongTimeString());

                    Console.WriteLine($"show the data in bufferQueue:{Transform.ToHexString(bufferQueue.ToArray())}");

                    //给帧长度赋值
                    frameLength = bufferQueue.ToArray()[1];

                    //数据的长度
                    Console.WriteLine($"frame length={String.Format("{0:X2}", frameLength)}");

                    //判断一帧完整的长度:(0x7F(1字节)+长度(1字节)+数据的长度frameLength(x字节)+CRC(2字节)),但是不代表数据是正确的
                    if (bufferQueue.Count >= 1 + 1 + frameLength + 2)
                    {
                        byte[] frameBuffer = new byte[1 + 1 + frameLength + 2];
                        Array.Copy(bufferQueue.ToArray(), 0, frameBuffer, 0, frameBuffer.Length);
                        //检查是否是有效数据
                        if (CommTools.crc_check(frameBuffer))
                        {
                            Console.WriteLine("frame is check ok,pick it");
                            frameCheckOk = true;
                        }
                        else
                        {
                            //无效数据
                            Console.WriteLine("bad frame,drop it.");
                            for (int i = 0; i < frameBuffer.Length; i++)
                            {
                                bufferQueue.Dequeue();
                            }

                        }

                        if (frameCheckOk)
                        {
                            frameCheckOk = false;
                            return frameBuffer;
                        }

                        //完成之后,将帧头标志设置为false,让其去处理下一帧的数据
                        isHeadRecive = false;
                    }



                }
                //长度不对就继续接受数据
            }

            return null;

        }


    }
}
